import re
import socket

# html文件路径
ROOT = './html'


def handle_client(client_socket):
    """处理客户端请求"""

    # 5. 接收浏览器的请求
    request = client_socket.recv(1024).decode('utf-8')
    # print(request)

    # 请求信息分行查看
    request_lines = request.splitlines()
    for i, line in enumerate(request_lines):
        print(i, line)

    # GET /index.html HTTP/1.1  正则匹配
    ret = re.match(r"([^/]*)([^ ]*)", request_lines[0])
    if ret:
        print("正则处理的数据：", ret.group(1))
        print("正则处理的数据：", ret.group(2))
        # 提取需要的文件名(包含路径)  这里是/index.html
        file_name = ret.group(2)  # /index.html
        # 不写index.html 也是主页
        if file_name == "/":
            file_name = "/index.html"

        # "./html/index.html"
        try:
            with open(ROOT + file_name, "r") as f:  # "./html/index.html"
                # 读取文件内容
                content = (200, f.read())  # 200 表示：http状态码
        except Exception as ret:
            content = (404, "404, 找不到您要的页面...")  # 404 表示：http状态码
    else:
        content = (500, "500, 系统异常...")  # 500 表示：http状态码

    # 组织相应 头信息(header)
    response_headers = "HTTP/1.1 %s OK\r\n" % content[0]  # 提取上述处理时的状态码
    response_headers += "Content-Type: text/html;charset=utf-8\r\n"
    response_headers += "\r\n"  # 用一个空的行与body进行隔开
    # 组织 内容(body)
    response_body = content[1].encode("utf-8")
    # 因为从文件读取出来的数据是二进制，而header是字符串，因此不能直接相加，需要分开发送
    # 先发送header
    client_socket.send(response_headers.encode("utf-8"))
    # 再发送文件的数据(body)
    client_socket.send(response_body)
    # 关闭客户端套接字
    client_socket.close()


def main():
    """作为程序的主控制入口"""
    # 1.创建tcp的套接字
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 设置端口复用  当服务器先close 即服务器端4次挥手之后资源能够立即释放，这样就保证了，下次运行程序时 可以立即绑定7788端口
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 2.绑定端口
    server_socket.bind(("", 7788))
    # 3.设置监听
    server_socket.listen(128)
    while True:
        # 获取客户端请求
        client_socket, client_addr = server_socket.accept()
        # 处理客户端请求
        handle_client(client_socket)


if __name__ == "__main__":
    main()
